package com.gzhryc.shared_device.oem.micro.iot;

import java.sql.SQLException;
import java.util.Date;

import com.gzhryc.common.ClassTools;
import com.gzhryc.common.DateTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.json.JsonTools;
import com.gzhryc.common.kafka.JFKafkaProducer;
import com.gzhryc.common.kafka.KafkaProducerFactory;
import com.gzhryc.common.kafka.models.KafkaMessage;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.shared_device.base.enums.ELogState;
import com.gzhryc.shared_device.base.models.OperateInfo;
import com.gzhryc.shared_device.cdcz.code.ICDCZBusinessEventListener;
import com.gzhryc.shared_device.cdcz.code.dao.db.CDCZOrder;
import com.gzhryc.shared_device.cdcz.code.dao.enums.CDCZOrderEnum;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderChargeLogService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderLogService;
import com.gzhryc.shared_device.cdcz.code.services.CDCZOrderService;
import com.gzhryc.shared_device.cdcz.core.enums.ECDCZPlugWorkState;
import com.gzhryc.shared_device.cdcz.core.models.CDCZChargeCloseNotify;
import com.gzhryc.shared_device.oem.code.KafkaEventConstants;
import com.gzhryc.shared_device.oem.code.business.EBusinessType;
import com.gzhryc.shared_device.oem.code.member.services.MemberBusinessOrderService;
import com.gzhryc.shared_device.oem.code.member.services.MemberWalletService;
import com.gzhryc.shared_device.oem.code.order.RedisCacheManager;
import com.gzhryc.shared_device.oem.code.order.event.OrderFinishEvent;
import com.gzhryc.shared_device.oem.code.place.services.PlaceBusinessConfigService;

public class CDCZBusinessEventListener implements ICDCZBusinessEventListener {

    static Logger log = Logger.getLogger(CDCZBusinessEventListener.class);

    @Override
    public int chargeCheck(String tradeNo, Double nowPower, Double nowCurrent, Double electricity, Integer chargedTime,OperateInfo operateInfo) {
        log.info("触发充电收费检查，订单号：{{0}}，当前功率：{{1}}，当前电量：{{2}}", tradeNo, nowPower, electricity);
        int result = 0;
        CDCZOrder useOrder = RedisCacheManager.getWorkingCDCZDeviceOrder(tradeNo);
        if (useOrder == null) {
            useOrder = CDCZOrderService.self(new Date()).getByTradeNo(tradeNo);
        }
        if (useOrder != null) {
            if(CDCZOrderEnum.State.Working.index().equals(useOrder.getState())) {
                //获取最大功率
                if (useOrder.getMaxUsePower() == null || nowPower > useOrder.getMaxUsePower()) {
                    useOrder.setMaxUsePower(nowPower);
                    CDCZOrderService.self(useOrder.getCreateDate()).updateMaxUsePower(useOrder.getTradeNo(),useOrder.getMaxUsePower());
                    RedisCacheManager.saveWorkingCDCZDeviceOrder(useOrder);
                }
            }else{
                if(CDCZOrderEnum.State.Opening.index().equals(useOrder.getState())) {
                    if (CDCZOrderService.self(useOrder.getCreateDate()).openingToWorking(useOrder)) {
                        chargeStart(useOrder);
                    }else {
                        log.error("设备开启成功，修改设备订单状态失败，订单号：{{0}}", useOrder.getTradeNo());
                        result = 1;
                    }
                }else {
                    log.error("设备订单非工作中，订单号：{{0}}，状态：{{1}}", useOrder.getTradeNo(), useOrder.getStateName() + "(" + useOrder.getState() + ")");
                    result = 1;
                }
            }
        } else {
            log.error("充电检查未找到相关订单，订单号：{{0}}", tradeNo);
        }
        return result;
    }

    @Override
    public void chargeStart(CDCZOrder deviceOrder) {
        //更新缓存
        RedisCacheManager.saveWorkingCDCZDeviceOrder(deviceOrder);
    }

    @Override
    public void finishCharge(CDCZOrder deviceOrder, CDCZChargeCloseNotify chargeCloseNotify, OperateInfo operateInfo) {
        //清理缓存，避免定时器重复处理
        RedisCacheManager.removeWorkingCDCZDeviceOrder(deviceOrder.getTradeNo());
        //获取最后收费时间
        Date lastDeductionDate = deviceOrder.getStartDate();
        if (deviceOrder.getLastDeductionDate() != null) {
            lastDeductionDate = deviceOrder.getLastDeductionDate();
        }
        //结算金额
        Long walletMoney = 0L;
        Integer stopMode = null;
        int times = 15;     //15分钟扣费一次

        Long minute = DateTools.differenceMinute(lastDeductionDate, new Date()) - 1;        //使用时长，1分钟免费

        Long payMoney = PlaceBusinessConfigService.self().getCDCZPayMoney(deviceOrder.getPlaceId(),deviceOrder.getMaxUsePower());

        Integer operateState = ELogState.Fail.index();
        String errorMsg = "充电结束，最后处理操作失败";

        if (payMoney != null && minute > 0) {
            Long count = minute / times;
            if(minute % times > 0){
                count = count + 1;
            }
            walletMoney = NumberTools.multiply(NumberTools.divide(payMoney, 4, 0), count);
        }

        if(ECDCZPlugWorkState.TimesFillStop.index().equals(chargeCloseNotify.getWorkState())){
            stopMode = CDCZOrderEnum.StopMode.TimesFillStop.index();
        }else if(ECDCZPlugWorkState.MaxPowerFillStop.index().equals(chargeCloseNotify.getWorkState())){
            stopMode = CDCZOrderEnum.StopMode.MaxPowerFillStop.index();
        }else if(ECDCZPlugWorkState.PowerFillStop.index().equals(chargeCloseNotify.getWorkState())){
            stopMode = CDCZOrderEnum.StopMode.PowerFillStop.index();
        }else if(ECDCZPlugWorkState.OutStop.index().equals(chargeCloseNotify.getWorkState())){
            stopMode = CDCZOrderEnum.StopMode.OutStop.index();
        }else if(ECDCZPlugWorkState.ForceStop.index().equals(chargeCloseNotify.getWorkState())){
            stopMode = CDCZOrderEnum.StopMode.ForceStop.index();
        }

        JdbcSession.begin();
        try {
            if (CDCZOrderService.self(deviceOrder.getCreateDate()).finishCharge(deviceOrder, payMoney, walletMoney, stopMode,chargeCloseNotify.getElectricity())) {
                operateInfo.setOperateNote(deviceOrder.getTradeNo() + "订单最后一次扣费");
                if (MemberWalletService.self().reduceMoney(deviceOrder.getMemberId(), walletMoney, operateInfo)) {
                    JdbcSession.commit();
                    operateState = ELogState.Success.index();
                    errorMsg = null;
                }
            } else {
                errorMsg = "充电结束，修改设备订单失败";
            }
        } catch (SQLException e) {
            log.error(e.getMessage(), e);
            errorMsg = e.getMessage();
        } catch (LogicException e) {
            log.error(e.getMessage(), e);
            errorMsg = e.getMessage();
        } finally {
            JdbcSession.end();
        }

        //添加日志
        operateInfo.setOperateNote("充电完成，最后一次扣费" + NumberTools.getMoneyLiStr(walletMoney) + "元，当前功率：" + deviceOrder.getMaxUsePower() + "，每小时收费：" + NumberTools.getMoneyLiStr(payMoney) + "元");
        CDCZOrderChargeLogService.self(deviceOrder.getCreateDate()).add(deviceOrder, operateInfo, operateState, errorMsg);
        operateInfo.setOperateNote("充电插座充电完成，" + CDCZOrderEnum.StopMode.note(stopMode));
        CDCZOrderLogService.self(deviceOrder.getCreateDate()).add(deviceOrder,operateInfo,operateState,errorMsg);

        if(ELogState.Success.index().equals(operateState)) {
            //同步会员订单
            deviceOrder = CDCZOrderService.self(deviceOrder.getCreateDate()).getByTradeNo(deviceOrder.getTradeNo());
            MemberBusinessOrderService.self(deviceOrder.getCreateDate()).finish(deviceOrder.getTradeNo(),deviceOrder.getMoney(),deviceOrder.getPayMoney(),deviceOrder.getWalletMoney());

            //触发订单完成
            JFKafkaProducer producer = KafkaProducerFactory.self().getProducer();
            if (producer != null) {
                OperateInfo temp = ClassTools.copy(new OperateInfo(), operateInfo);
                OrderFinishEvent event = new OrderFinishEvent(EBusinessType.CDCZ.index(), deviceOrder.getTradeNo(), deviceOrder.getCreateDate(), temp);
                KafkaMessage kafkaMessage = new KafkaMessage(KafkaEventConstants.TOPIC_Order, KafkaEventConstants.KEY_OrderFinish, JsonTools.toJson(event));
                producer.send(kafkaMessage);
            }else{
                log.error("未初始化消息队列，订单{{0}}未触发完成事件",deviceOrder.getTradeNo());
            }
        }
    }
}
